package com.ruoyi.system.service.impl;



import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.concurrent.ForkJoinPool;

import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.system.Dto.TaskSubDto;
import com.ruoyi.system.domain.TaskSubDto1;
import com.ruoyi.system.constant.Constants;
import com.ruoyi.system.domain.Subjects;
import com.ruoyi.system.domain.TaskConfig;
import com.ruoyi.system.domain.TaskSub;
import com.ruoyi.system.mapper.TaskConfigMapper;
import com.ruoyi.system.mapper.TaskSubMapper;
import com.ruoyi.system.utils.OutStream;
//import matlabcontrol.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.system.mapper.IbrainTaskMapper;
import com.ruoyi.system.domain.IbrainTask;
import com.ruoyi.system.service.IIbrainTaskService;

import static com.ruoyi.system.controller.iBrainController.*;
import static com.ruoyi.system.utils.Util.getsub;

/**
 * 【请填写功能名称】Service业务层处理
 *
 * @author ruoyi
 * @date 2023-12-23
 */
@Service
public class IbrainTaskServiceImpl implements IIbrainTaskService
{
    @Autowired
    private IbrainTaskMapper ibrainTaskMapper;

    @Autowired
    private TaskConfigMapper taskConfigMapper;

    @Autowired
    private TaskSubMapper taskSubMapper;

    /**
     * 查询【请填写功能名称】
     *
     * @param id 【请填写功能名称】主键
     * @return 【请填写功能名称】
     */
    @Override
    public IbrainTask selectIbrainTaskById(Long id)
    {
        return ibrainTaskMapper.selectIbrainTaskById(id);
    }

    /**
     * 查询【请填写功能名称】列表
     *
     * @param ibrainTask 【请填写功能名称】
     * @return 【请填写功能名称】
     */
    @Override
    public List<IbrainTask> selectIbrainTaskList(IbrainTask ibrainTask)
    {
        return ibrainTaskMapper.selectIbrainTaskList(ibrainTask);
    }

    /**
     * 新增【请填写功能名称】
     *
     * @param ibrainTask 【请填写功能名称】
     * @return 结果
     */
    @Override
    public int insertIbrainTask(IbrainTask ibrainTask)
    {
        return ibrainTaskMapper.insertIbrainTask(ibrainTask);
    }

    /**
     * 修改【请填写功能名称】
     *
     * @param ibrainTask 【请填写功能名称】
     * @return 结果
     */
    @Override
    public int updateIbrainTask(IbrainTask ibrainTask)
    {
        return ibrainTaskMapper.updateIbrainTask(ibrainTask);
    }

    /**
     * 批量删除【请填写功能名称】
     *
     * @param ids 需要删除的【请填写功能名称】主键
     * @return 结果
     */
    @Override
    public int deleteIbrainTaskByIds(Long[] ids)
    {
        return ibrainTaskMapper.deleteIbrainTaskByIds(ids);
    }

    /**
     * 删除【请填写功能名称】信息
     *
     * @param id 【请填写功能名称】主键
     * @return 结果
     */
    @Override
    public int deleteIbrainTaskById(Long id)
    {
        return ibrainTaskMapper.deleteIbrainTaskById(id);
    }

    @Override
    public IbrainTask gettaskid() {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        Long userId = loginUser.getUserId();
        IbrainTask ibrainTask = ibrainTaskMapper.getibraintask(userId);
        if (ibrainTask==null){
            ibrainTask = new IbrainTask();
            ibrainTask.setUserId(userId);
            Long status = 0L;
            ibrainTask.setStatus(status);
            LocalDateTime currentTime = LocalDateTime.now();
            // 定义日期时间格式
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            // 将当前时间格式化为字符串
            String formattedTime = currentTime.format(formatter);
            ibrainTask.setSubTime(formattedTime);
            ibrainTaskMapper.insertIbrainTask(ibrainTask);
            return ibrainTask;
        }

        return ibrainTask;
    }

    @Override
    public void reload() {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        Long userId = loginUser.getUserId();
        IbrainTask ibrainTask = new IbrainTask();
        ibrainTask.setUserId(userId);
        Long status = 0L;
        ibrainTask.setStatus(status);
        LocalDateTime currentTime = LocalDateTime.now();
        // 定义日期时间格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        // 将当前时间格式化为字符串
        String formattedTime = currentTime.format(formatter);
        ibrainTask.setSubTime(formattedTime);
        ibrainTaskMapper.insertIbrainTask(ibrainTask);
    }

    @Override
    public void updateibraintaskstatus(Long id) {
        IbrainTask ibrainTask = ibrainTaskMapper.selectIbrainTaskById(id);
        int status234 = ibrainTaskMapper.select234status();
        if(status234>=Constants.maxqueue){
            int queue = ibrainTaskMapper.selectmaxqueue();
            ibrainTask.setStatus(1l);
            ibrainTask.setQueue(Long.valueOf(queue+1));
            ibrainTaskMapper.updateIbrainTask(ibrainTask);
        }
        else {
            ibrainTask.setStatus(2l);
            ibrainTask.setQueue(0l);
            ibrainTaskMapper.updateIbrainTask(ibrainTask);
        }
    }

    @Override
    public void updatemanyibraintaskstatus() {
        int status234 = ibrainTaskMapper.select234status();
        if(status234<Constants.maxqueue){
            IbrainTask ibrainTask = new IbrainTask();
            ibrainTask.setStatus(1l);
            List<IbrainTask> ibrainTasks = ibrainTaskMapper.selectIbrainTaskList(ibrainTask);
            for(IbrainTask ibt:ibrainTasks){
                Long que = ibt.getQueue()-1;
                if(que!=0){
                    ibt.setQueue(que);
                    ibrainTaskMapper.updateIbrainTask(ibt);
                }
                else {
                    ibt.setQueue(que);
                    ibt.setStatus(2l);
                    ibrainTaskMapper.updateIbrainTask(ibt);
                }
            }
        }
    }

    @Override
    public void runstatus2to3(){
        IbrainTask ibrainTask = new IbrainTask();
        ibrainTask.setStatus(2l);
        List<IbrainTask> ibrainTasks = ibrainTaskMapper.selectIbrainTaskList(ibrainTask);
        for(IbrainTask ibt:ibrainTasks){
            ibt.setStatus(3l);
            TaskConfig t1 = new TaskConfig();
            t1.setTaskid(ibt.getId());
            TaskConfig t2 = taskConfigMapper.selectTaskConfigListNew(t1);
            int count = getsub(t2.getSubject()).size();
            TaskConfig taskConfigtemp0 = new TaskConfig();
            taskConfigtemp0.setTaskid(ibt.getId());
            TaskConfig tc = taskConfigMapper.selectTaskConfigListNew(taskConfigtemp0);
            int min=0;
            if(tc.getType2()==null){
                min = count*Constants.t1_time;
            }
            else
                min = count*Constants.t1bold_time;
            LocalDateTime currentDateTime = LocalDateTime.now();
            LocalDateTime newDateTime = currentDateTime.plusMinutes(min);
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            String formattedDateTime = newDateTime.format(formatter);
            ibt.setTime(formattedDateTime);
            ibrainTaskMapper.updateIbrainTask(ibt);
        }

/*        ForkJoinPool forkJoinPool = new ForkJoinPool();
        forkJoinPool.submit(() ->
                ibrainTasks.parallelStream().forEach(ibt -> {
                    TaskConfig taskConfigtemp = new TaskConfig();
                    taskConfigtemp.setTaskid(ibt.getId());
                    TaskConfig taskConfig = taskConfigMapper.selectTaskConfigListNew(taskConfigtemp);
                    IbrainTask ibrainTask3 = ibrainTaskMapper.selectIbrainTaskById(ibt.getId());
                    String task = ibrainTask3.getId().toString()+"_"+ibrainTask3.getUserId();
                    List<Subjects> subjectsList = new ArrayList<>();
                    if(taskConfig.getType2()!=null){
                        String matSliceOrdertem=returnSliceOrder(taskConfig.getSliceOrder());
                        String[] parts = matSliceOrdertem.split(" ");
                        int[] matSliceOrder = new int[parts.length];
                        for(int i=0;i<parts.length;i++){
                            matSliceOrder[i]=Integer.parseInt(parts[i]);
                        }
                        //SliceOrder转为int[]数组
                        String[] rows = taskConfig.getBoundingBox().split(";");
                        int numRows = rows.length;
                        int numCols = rows[0].split(" ").length;
                        double[] matBoundingBox1 = new double[3];
                        double[] matBoundingBox2 = new double[3];
                        double[][] matBoundingBox = new double[numRows][numCols];
                        for (int i = 0; i < numRows; i++) {
                            String[] nums = rows[i].split(" ");
                            for (int j = 0; j < numCols; j++) {
                                matBoundingBox[i][j] =Double.parseDouble(nums[j]);
                            }
                        }
                        for(int i=0;i<3;i++){
                            matBoundingBox1[i]=matBoundingBox[0][i];
                            matBoundingBox2[i]=matBoundingBox[1][i];
                        }
                        //BoundingBox转为2x3 double[][]数组
                        String[] parts2 = taskConfig.getVoxelSize().split(" ");
                        double[] matVoxelSize = new double[parts2.length];
                        for(int i=0;i<parts2.length;i++){
                            matVoxelSize[i]=Double.parseDouble(parts2[i]);
                        }



                        //用户列表------------------------
                        subjectsList = getsub(taskConfig.getSubject());
                        int num = subjectsList.size();
                        String s[] = new String[num];
                        for (int ii=0;ii<num;ii++){
                            s[ii]= subjectsList.get(ii).getName();
                        }


                        Object[] input = {taskConfig.getType1(),taskConfig.getType2(),s,num,task,matSliceOrder,matBoundingBox1,matBoundingBox2,matVoxelSize,taskConfig.getBOLDTR(),taskConfig.getSkipTR(),taskConfig.getRefslic(),taskConfig.getSmoothFWHM(),taskConfig.getFilterLB(),taskConfig.getFilterHB()};
                        MatlabProxyFactoryOptions.Builder builder = new MatlabProxyFactoryOptions.Builder();
                        builder.setHidden(false);
                        builder.setUsePreviouslyControlledSession(true);
                        File matlabfile = new File(Constants.pth+File.separator);
                        builder.setMatlabStartingDirectory(matlabfile);
                        builder.setProxyTimeout(300000);
                        MatlabProxyFactory factory = new MatlabProxyFactory(builder.build());
                        MatlabProxy proxy = null;
                        try {
                            proxy = factory.getProxy();
                        } catch (MatlabConnectionException e) {
                            throw new RuntimeException(e);
                        }
                        try {
                            proxy.feval("uploadsub_fun", input);
                        } catch (MatlabInvocationException e) {
                            throw new RuntimeException(e);
                        }
                        try {
                            proxy.exit();
                        } catch (MatlabInvocationException e) {
                            throw new RuntimeException(e);
                        }
                    }
                    else {
                        subjectsList = getsub(taskConfig.getSubject());
                        int num = subjectsList.size();
                        String s[] = new String[num];
                        for (int ii=0;ii<num;ii++){
                            s[ii]= subjectsList.get(ii).getName();
                        }
                        Object[] input = {taskConfig.getType1(),s,num,task};
                        MatlabProxyFactoryOptions.Builder builder = new MatlabProxyFactoryOptions.Builder();
                        builder.setHidden(false);
                        builder.setUsePreviouslyControlledSession(true);
                        File matlabfile = new File(Constants.pth+File.separator);
                        builder.setMatlabStartingDirectory(matlabfile);
                        builder.setProxyTimeout(300000);
                        MatlabProxyFactory factory = new MatlabProxyFactory(builder.build());
                        MatlabProxy proxy = null;
                        try {
                            proxy = factory.getProxy();
                        } catch (MatlabConnectionException e) {
                            throw new RuntimeException(e);
                        }
                        try {
                            proxy.feval("uploadsub", input);
                        } catch (MatlabInvocationException e) {
                            throw new RuntimeException(e);
                        }
                        try {
                            proxy.exit();
                        } catch (MatlabInvocationException e) {
                            throw new RuntimeException(e);
                        }
                    }


                    //MatlabProxyFactoryOptions设置matlab
                    MatlabProxyFactoryOptions.Builder builder = new MatlabProxyFactoryOptions.Builder();
                    //设置matlab GUI隐藏，Windows操作系统中 MATLAB command window还是会显示(如果想让MATLAB command window也隐藏，需要用到JNA)，Linux会全部隐藏
                    builder.setHidden(false);
                    //设置使用已存在的matlab，设置这个不会运行一次matlab启动一次
                    builder.setUsePreviouslyControlledSession(true);
                    File matlabfile = new File(Constants.pth+File.separator);
                    //设置matlab启动时路径
                    builder.setMatlabStartingDirectory(matlabfile);
                    //设置获取代理的时间，这里的300000有的时候不够，改长一点就可以
                    builder.setProxyTimeout(600000);
                    MatlabProxyFactory factory = new MatlabProxyFactory(builder.build());
                    //获取matlab代理(用的是代理模式)
                    MatlabProxy proxy = null;
                    try {
                        proxy = factory.getProxy();
                    } catch (MatlabConnectionException e) {
                        throw new RuntimeException(e);
                    }
                    //这个有好几种方法
                    Object[] input = {taskConfig.getType1(),task,1,taskConfig.getLanguage(),taskConfig.getTaskid()};   //addmatlab
                    try {
                        proxy.feval("runiBrain", input);
                    } catch (MatlabInvocationException e) {
                        throw new RuntimeException(e);
                    }
                    System.out.println("------step1-end----------");
                    try {
                        proxy.exit();
                    } catch (MatlabInvocationException e) {
                        throw new RuntimeException(e);
                    }


                    //MatlabProxyFactoryOptions设置matlab
                    MatlabProxyFactoryOptions.Builder builder1 = new MatlabProxyFactoryOptions.Builder();
                    //设置matlab GUI隐藏，Windows操作系统中 MATLAB command window还是会显示(如果想让MATLAB command window也隐藏，需要用到JNA)，Linux会全部隐藏
                    builder1.setHidden(false);
                    //设置使用已存在的matlab，设置这个不会运行一次matlab启动一次
                    builder1.setUsePreviouslyControlledSession(false);
                    File matlabfile1 = new File(Constants.pth+File.separator);
                    //设置matlab启动时路径
                    builder1.setMatlabStartingDirectory(matlabfile1);
                    //设置获取代理的时间，这里的300000有的时候不够，改长一点就可以
                    builder1.setProxyTimeout(600000);
                    System.out.println("0-------------------");
                    MatlabProxyFactory factory1 = new MatlabProxyFactory(builder1.build());
                    //获取matlab代理(用的是代理模式)
                    System.out.println("1-------------------");
                    MatlabProxy proxy1 = null;
                    try {
                        proxy1 = factory1.getProxy();
                    } catch (MatlabConnectionException e) {
                        throw new RuntimeException(e);
                    }
                    System.out.println("2-------------------");
                    //这个有好几种方法
                    Object[] input1 = {taskConfig.getType1(),task,2,taskConfig.getLanguage(),taskConfig.getTaskid()};   //addmatlab
                    try {
                        proxy1.feval("runiBrain", input1);
                    } catch (MatlabInvocationException e) {
                        throw new RuntimeException(e);
                    }
                    System.out.println("------step2-end----------");
                    try {
                        proxy1.exit();
                    } catch (MatlabInvocationException e) {
                        throw new RuntimeException(e);
                    }
                    System.out.println("------all-end----------");
                })
        ).join();
        forkJoinPool.shutdown();*/


/*        ForkJoinPool forkJoinPool = new ForkJoinPool();
        forkJoinPool.submit(() ->
                ibrainTasks.parallelStream().forEach(ibt -> {

                    TaskConfig taskConfigtemp = new TaskConfig();
                    taskConfigtemp.setTaskid(ibt.getId());
                    TaskConfig taskConfig = taskConfigMapper.selectTaskConfigListNew(taskConfigtemp);
                    IbrainTask ibrainTask3 = ibrainTaskMapper.selectIbrainTaskById(ibt.getId());

                    String task = ibrainTask3.getId().toString()+"_"+ibrainTask3.getUserId();
                    String subjectsList = taskConfig.getSubject();
                    Long taskid = ibt.getId();
                    int tid = taskid.intValue();
                    Long lan = taskConfig.getLanguage();
                    int iseng = lan.intValue();
                    int t1;
                    if(taskConfig.getType1().equals("T1Img"))
                        t1=0;
                    else
                        t1=1;

                    Process proc;
                    try {
                        String workingdic = Constants.pth+File.separator+"test_data"+File.separator+task;
                        String py = "python "+Constants.pth+File.separator+"runiBrain.py --WorkingDir=\"" + workingdic + "\" --subjects=\""+subjectsList+
                                "\" --taskid="+tid+" --IsOneKeyFromT1Raw="+t1+" --MultipleProcess=1 --IsReportWholeBrain=1 --IsToIndSpace=1 --IsMinimumOutput=1"+
                                " --IsReportInEng="+iseng;

                        proc = Runtime.getRuntime().exec(py);// 执行py文件

                        OutStream error= new OutStream(proc.getErrorStream(),"Error");
                        OutStream output= new OutStream(proc.getInputStream(),"OutPut");
                        error.start();
                        output.start();
                        proc.waitFor(); //等待子进程结束

                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                })
        ).join();
        forkJoinPool.shutdown();*/


        for (IbrainTask ibt:ibrainTasks){
            {

                TaskConfig taskConfigtemp = new TaskConfig();
                taskConfigtemp.setTaskid(ibt.getId());
                TaskConfig taskConfig = taskConfigMapper.selectTaskConfigListNew(taskConfigtemp);
                IbrainTask ibrainTask3 = ibrainTaskMapper.selectIbrainTaskById(ibt.getId());

                String task = ibrainTask3.getId().toString()+"_"+ibrainTask3.getUserId();
                String subjectsList = taskConfig.getSubject();
                Long taskid = ibt.getId();
                int tid = taskid.intValue();
                Long lan = taskConfig.getLanguage();
                int iseng = lan.intValue();

                int t1;
                if(taskConfig.getType1().equals("T1Img"))
                    t1=0;
                else
                    t1=1;
                Long isclinical = taskConfig.getClinical();
                Process proc;
                try {

                    String workingdic = Constants.pth + File.separator + "test_data" + File.separator + task;
/*                    String[] cmd = {
                            "python",
                            Constants.pth + File.separator + "runiBrain.py",
                            "--WorkingDir=" + workingdic,
                            "--subjects=" + subjectsList,  // 不需要手动加入双引号
                            "--taskid=" + tid,
                            "--IsOneKeyFromT1Raw=" + t1,
                            "--MultipleProcess=1",
                            "--IsReportWholeBrain=1",
                            "--IsToIndSpace=1",
                            "--IsMinimumOutput=1",
                            "--IsReportInEng=" + iseng
                    };*/
//conda activate iBrainStable &&
                    String py = "python "+Constants.pth + File.separator + "runiBrain.py"+" --WorkingDir="+workingdic+" --subjects="+subjectsList+
                            " --taskid="+tid+" --IsOneKeyFromT1Raw="+t1+" --MultipleProcess=1 --IsReportWholeBrain=1 --IsToIndSpace=1 --IsMinimumOutput=1 --IsReportInEng="+iseng+" --isclinical="+isclinical;
                    System.out.println("------------------------------------------222222222222---------------------------");
                    System.out.println(py);  // 打印用于调试
                    System.out.println("------------------------------------------222222222222---------------------------");

                    proc = Runtime.getRuntime().exec(py);  // 直接执行数组形式的命令


                    OutStream error= new OutStream(proc.getErrorStream(),"Error");
                    OutStream output= new OutStream(proc.getInputStream(),"OutPut");
                    error.start();
                    output.start();
                    proc.waitFor(); //等待子进程结束

                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }

    @Override
    public List<TaskSubDto> getdownloadsub() {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        Long userId = loginUser.getUserId();
        List<TaskSubDto> taskSubDtos = new ArrayList<>();
        List<IbrainTask> ibrainTasks = ibrainTaskMapper.select45status(userId);
        for(IbrainTask ibt:ibrainTasks){
            List<TaskSub> taskSubs = taskSubMapper.selectbytid(ibt.getId());
            for(TaskSub ts:taskSubs){
                if(ts.getIsover()!=null&&ts.getIsover()==1){
                    TaskSubDto taskSubDto = new TaskSubDto();
                    taskSubDto.setId(ts.getId());
                    taskSubDto.setTaskId(ibt.getId());
                    taskSubDto.setTaskid(ibt.getId());
                    taskSubDto.setSubname(ts.getSubname());
                    taskSubDto.setStartTime(ts.getStartTime());
                    taskSubDto.setEndTime(ts.getEndTime());
                    taskSubDtos.add(taskSubDto);
                }
            }
        }
        return taskSubDtos;
    }

    @Override
    public List<TaskSubDto> getdownloadsubbysearch(TaskSubDto1 taskSubDto) {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        Long userId = loginUser.getUserId();
        taskSubDto.setUserId(userId);
        List<TaskSubDto1> taskSubDto1s = taskSubMapper.select45statusbysearch(taskSubDto);
        List<TaskSubDto> taskSubDtos = new ArrayList<>();
        for (TaskSubDto1 taskSubDto1:taskSubDto1s){
            TaskSubDto taskSubDtotemp = new TaskSubDto();
            taskSubDtotemp.setId(taskSubDto1.getId());
            taskSubDtotemp.setTaskId(taskSubDto1.getTaskId());
            taskSubDtotemp.setTaskid(taskSubDto1.getTaskId());
            taskSubDtotemp.setSubname(taskSubDto1.getSubname());
            taskSubDtotemp.setStartTime(taskSubDto1.getStartTime());
            taskSubDtotemp.setEndTime(taskSubDto1.getEndTime());
            taskSubDtos.add(taskSubDtotemp);
        }
        return taskSubDtos;
    }

    @Override
    public Long getuidbytaskid(Long taskid) {
        IbrainTask ibrainTask = ibrainTaskMapper.selectIbrainTaskById(taskid);
        return ibrainTask.getUserId();
    }


}
